home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / General App Samples / QD PICT To GX Picture ƒ / graphics shell.c next >
Encoding:
C/C++ Source or Header  |  1996-03-20  |  12.0 KB  |  373 lines  |  [TEXT/MMCC]

  1. /**  
  2.  --        graphics shell.c
  3.  --
  4.  --        This file is a shell that can be used to build QuickDraw GX graphics applications.  
  5.  --        It contains all of the required calls to use the "new" QuickDraw GX routines and 
  6.  --        QuickDraw (i.e. windows) together. It will put up one window. You "quit" 
  7.  --        the application by clicking in the close box.  This shell does not use a menu.
  8.  --        
  9.  --     The application is expected to supply the following functions which are called
  10.  --        by this shell:
  11.  --
  12.  --            void DoInitialization(WindowPtr);
  13.  --            void DoDraw(WindowPtr);
  14.  --            void DoDispose(WindowPtr);
  15.  --            void DoClick(gxPoint, WindowPtr);
  16.  --            void DoIdle(WindowPtr);
  17.  --
  18.  --
  19.  --     Change History:         
  20.  --
  21.  --        4/94    - Added the gxPoint as a parameter to the DoClick( gxPoint mouseLoc, WindowPtr myWindow ) 
  22.  --                  function to support hit testing.  PLA
  23.  --
  24.  --        3/94    - Removed the following varaibles: gDebugging & gGiveMeValidation see the comments
  25.  --                  for details (below). 
  26.  --
  27.  --                - Added a Gestalt check to see if GX has been installed. Added extensive error 
  28.  --                  checking to make sure the GX graphics client has been created and the GX heap
  29.  --                  correctly allocated. This shell will shut down at start-up and alert the user
  30.  --                  to the problem and bail if: GX is not installed, we cannot create the graphics
  31.  --                  client, or create a GX heap.  PLA
  32.  --
  33.  --        12/93    Updated the comment above the GXNewGraphicsCLient call to reflect the new fucntionality
  34.  --                of this call in ß3. I also removed the work around with GXConvertQDPoint (..) where
  35.  --                the call would not survive validation under ß2. Under ß3 the call suceeds when validation
  36.  --                is set.   PLA
  37.  --
  38.  --        8/93    - Updated this file to run with the QD GX ß2 "GX-ified" interfaces
  39.  --                - worked around a problem with GXConvertQDPoint (..) see the comments within
  40.  --                  the GetWindowBoundsShape (..) call for details (below).  PLA
  41.  --
  42.  --        6/92    Made the following variables global: gDebugging, gGiveMeValidation,gGraphicsHeapSize. 
  43.  --                See the comments for detail in this file.  PLA
  44.  --
  45.  --        6/91    Updated the shell to reflect the changes in "Graphics" v1.0d21.2.  PLA
  46.  --
  47.  --        3/90    New  - PLA
  48.  --
  49.  --
  50.  --        © Apple Computer, Inc. 1990 - 1994  All rights reserved
  51.  --                                
  52. **/
  53.  
  54.  
  55. #include <Desk.h>
  56. #include <Events.h>
  57. #include <Fonts.h>
  58. #include <Windows.h>
  59. #include <Memory.h>
  60. #include <ToolUtils.h>
  61. #include <Quickdraw.h>
  62. #include <GestaltEqu.h>
  63.  
  64. #include <GXEnvironment.h>
  65. #include <GXGraphics.h>
  66. #include <GXEnvironment.h>
  67. #include <GXErrors.h>
  68. #include "GraphicsLibraries.h"
  69.  
  70. #include "graphics shell.h"
  71.  
  72. #define    kOSEvent                                    app4Evt    // event used by MultiFinder
  73. #define    kSuspendResumeMessage            1        // high byte of suspend/resume event message
  74. #define    kResumeMask                                1        // bit of message field for resume vs. suspend
  75.  
  76.  
  77. #if defined(powerc) || defined(__powerc)
  78.     QDGlobals    qd;
  79. #endif
  80.  
  81.  
  82. WindowPtr         gWindow, whichWindow;
  83.  
  84. EventRecord        gtheEvent;
  85. gxShape             gWindowBoundsShape;
  86. gxViewPort        gTheWindowsViewPort;    
  87.  
  88. /**------ Function Prototypes -----**/
  89. void main(void);
  90. gxShape GetWindowBoundsShape(void);
  91. Boolean EventLoop(void);
  92. void SetUpGXDebuggingWorld (Boolean GXDebuggingInstalled);
  93.  
  94. /*------ main -----------------------------------------------------------------------------------------*/
  95.  
  96. void main()
  97. {        
  98.     CursHandle        theCurs; 
  99.     long                    theFeature;
  100.     Boolean                debuggingInitInstalled = false;
  101.     
  102.     //
  103.     //   Generic heap initialization.
  104.     //
  105.     MaxApplZone(); 
  106.     MoreMasters(); MoreMasters(); MoreMasters(); 
  107.     MoreMasters(); MoreMasters(); MoreMasters(); 
  108.  
  109.     //
  110.     //   Initialize the toolbox 
  111.     //
  112.      InitGraf(&qd.thePort);
  113.     InitFonts();
  114.     InitWindows();
  115.     InitCursor();
  116.  
  117.     theCurs = GetCursor(watchCursor);
  118.     SetCursor(*theCurs);
  119.  
  120.     //
  121.     //    Check to see if QuickDraw GX is installed. If not, alert the user...
  122.     //
  123.     if ( (Gestalt(gestaltGraphicsVersion, &theFeature) == noErr) )
  124.     {
  125.         gxGraphicsClient     newClient;
  126.         
  127.         //
  128.         //    The GX gestaltGraphicsAttr Gestalt attribute can be used to determine if:
  129.         //    the graphics piece of GX has been loaded, the GX debugging init is installed, or
  130.         //    your are running the PowerPC version. 
  131.         //
  132.         //    In our case, we only need to know if the debugging init was installed. If it is,
  133.         //    we will enable the GX validation and notice handling features.We define 
  134.         //    debuggingInitInstalled as true to enable GX validation and notice handler
  135.         //  within the SetUpGXDebuggingWorld function.
  136.         //
  137.         if ( (Gestalt(gestaltGraphicsAttr, &theFeature) == noErr) )
  138.           if ( (theFeature & gestaltGraphicsIsDebugging) == gestaltGraphicsIsDebugging ) 
  139.              debuggingInitInstalled = true;
  140.     
  141.  
  142.         newClient = GXNewGraphicsClient(nil, gGraphicsHeapSize * 1024, 0L);
  143.  
  144.         //
  145.         //    After we attempted to create the graphics client, we need to determine if the call
  146.         //  succeeded. If the call did not (as in the case for all GX functions), "newClient" will
  147.         //    be nil. If it is, we alert the user to the problem. Otherwise, we will attempted to 
  148.         //    allocate the GX heap below...
  149.         //        
  150.         if ( newClient ) 
  151.         {
  152.             //
  153.             //    Initialize the new graphics environment and create the GX heap.
  154.             //
  155.             GXEnterGraphics();
  156.  
  157.             //
  158.             //    Calling GXEnterGraphics allocates the memory within the GX heap. The only reason the
  159.             //  call would not succeed is if there is not enough memory. In this case, the graphics 
  160.             //  error which will be posted is -27999 (out of memory). At this point, we have not 
  161.             //    installed an error handler, so we check for the error number corresponding to the 
  162.             //  out of memory error.
  163.             //
  164.             if ( GXGetGraphicsError( nil ) != -27999 ) 
  165.             {
  166.                 SetUpGXDebuggingWorld (debuggingInitInstalled);
  167.  
  168.                 //
  169.                 //    Create a window and attach a GX viewPort to it. By attaching the viewPort to 
  170.                 //    the window will make sure that when a user moves or resizes the window all of
  171.                 //    the GX drawing will occur within window. 
  172.                 //
  173.                 //    By the way, you cannot directly manipulate the parent viewPort attached to the
  174.                 //    window, you will recieve a graphics error. This viewPort can only be manipulated
  175.                 //  by the GX system. If you want to manipulate a viewPort attached to a window, it
  176.                 //     _must_ be a child viewPort attached to the the parent viewPort attached to the
  177.                 //    window.
  178.                 //
  179.                 gWindow = NewWindow(nil, &gWindowQDRect, gWindowTitle, true, noGrowDocProc,
  180.                                    (WindowPtr)-1L, true, 0L);
  181.                                    
  182.                 gTheWindowsViewPort = GXNewWindowViewPort(gWindow);
  183.  
  184.                 GXIgnoreGraphicsNotice(transform_already_set);
  185.                 SetDefaultViewPort(gTheWindowsViewPort);
  186.                 GXPopGraphicsNotice();
  187.  
  188.                 //
  189.                 //  Get the global bounds of the window.
  190.                 //
  191.                 gWindowBoundsShape = GetWindowBoundsShape();
  192.  
  193.                  //
  194.                  //    Create the GX shapes we are going to draw to the window. 
  195.                  //
  196.                  DoInitialization(gWindow);
  197.  
  198.                 SetCursor(&qd.arrow);  
  199.     
  200.                 while (EventLoop())
  201.                       DoIdle(gWindow);   // loop until the window is closed
  202.  
  203.                 DoDispose(gWindow);
  204.     
  205.                 GXExitGraphics();     // Deallocate all of the default structures
  206.                 GXDisposeGraphicsClient(newClient);
  207.         
  208.             } else {
  209.                 //
  210.                 //     Since, we can not allocate the requested size for our GX heap, we need to throw
  211.                 //  away the client we created and alert the user that there is not enough memory to
  212.                 //  continue.
  213.                 //
  214.                 //    However, you could try to create a smaller GX heap. If you decide to try to create
  215.                 //     a smaller GX heap which would meet the needs of your application, you need to 
  216.                 //     dispose of the client you had originally created. Why? The original client 
  217.                 //    contains the GX heap size requested, which was too big, therefore you need to 
  218.                 //    dispose of it and create a client requesting a smaller size and call GXEnterGraphics
  219.                 //     and check for an error. 
  220.                 //
  221.                 GXDisposeGraphicsClient( newClient );
  222.                 DebugStr ("\p Unfortunately, there is not enough memory for GX, please quit an app...");
  223.             }
  224.           }
  225.  
  226.     } else DebugStr ("\p Unfortunately, you have not installed QuickDraw GX, I can't run without GX...");
  227.     
  228. }
  229.  
  230.  
  231.  
  232. /*------ SetUpGXDebuggingWorld ------------------------------------------------------------------------*/
  233. //
  234. //    This function enables the GX error handling capabilities and validation routines. The validation
  235. //    routines are only enabled, if the user has installed the QuickDraw GX debugging init. These routines
  236. //    are not available with the non-debugging init. Calling them when they are not installed will not 
  237. //    cause any problems, but it will cause unnecessary work to be done by your application and the GX 
  238. //    dispatcher.
  239. //
  240. void SetUpGXDebuggingWorld (Boolean debuggingInitInstalled)
  241. {
  242.       // 
  243.     //    We set-up GX validation, if the user has installed the "GXGraphics (debug)" init (formerly
  244.     //    named "aSecretGraphics.debug). This validation setting is the reccommended setting while
  245.     //    you are developing your GX application. As you increase the amount of validation, the drawing
  246.     //    speed will SLOW down due to all of the internal checking. 
  247.     //
  248.     //    For additional details regarding the various levels of validation, please see the
  249.     //    QuickDraw GX : Environment & Utilities book.
  250.     //
  251.     if ( debuggingInitInstalled ) GXSetValidation(gxPublicValidation + gxTypeValidation); 
  252.  
  253.     // 
  254.     //    Calling SetGraphicsLibraryErrors will install a GX error and warning handler. This
  255.     //    call is provided by the QuickDraw GX "graphics debugging library". Any time a GX error
  256.     //    or warning is generated, it will be posted to Macsbug.
  257.     //
  258.     SetGraphicsLibraryErrors ();
  259.         
  260.     //
  261.     //    If the user has installed the GX debugging version, we install a notice handler. Why? The
  262.     //    GX notice handling capabilities are only available with the debugging version.
  263.     //
  264.     if ( debuggingInitInstalled ) SetGraphicsLibraryNotices();
  265. }
  266.  
  267.  
  268.  
  269. /*------ GetWindowBoundsShape -------------------------------------------------------------------------*/
  270.  
  271. gxShape  GetWindowBoundsShape()
  272. {
  273.     Rect                theRect;
  274.     Point                QDtopLeft;
  275.     Point                QDbotRight;
  276.     gxPoint                QDGXtopLeft;
  277.     gxPoint                QDGXbotRight;
  278.     gxRectangle            theQDGXRect;
  279.     
  280.     //
  281.     // The QuickDraw rect and points which represent the portRect of the window. 
  282.     //
  283.     theRect = gWindow->portRect;
  284.     QDtopLeft.h = theRect.left;
  285.     QDtopLeft.v = theRect.top;
  286.     QDbotRight.h = theRect.right;
  287.     QDbotRight.v = theRect.bottom;
  288.      
  289.     //
  290.     //  Convert the global Quickdraw coordinates to local fixed coordinates.
  291.     //
  292.     GXConvertQDPoint(&QDtopLeft, 0, &QDGXtopLeft);
  293.     GXConvertQDPoint(&QDbotRight, 0, &QDGXbotRight);
  294.  
  295.     //
  296.     //  Setup the dimensions for "gWindowBoundsShape"
  297.     //
  298.     theQDGXRect.top = QDGXtopLeft.y;
  299.     theQDGXRect.left = QDGXtopLeft.x;
  300.     theQDGXRect.bottom = QDGXbotRight.y;
  301.     theQDGXRect.right = QDGXbotRight.x;
  302.     
  303.     return (GXNewRectangle(&theQDGXRect));
  304. }
  305.  
  306.  
  307.  
  308. /*------ EventLoop ------------------------------------------------------------------------------------*/
  309.  
  310. Boolean EventLoop()
  311. {
  312.     static long     sleep = 0;
  313.  
  314.     WaitNextEvent(everyEvent, >heEvent, sleep, nil);
  315.          
  316.     switch(gtheEvent.what)
  317.     {                    
  318.         case updateEvt:
  319.                 BeginUpdate((WindowPtr) gtheEvent.message);
  320.                 SetPort(gWindow);
  321.                 DoDraw(gWindow);
  322.                 EndUpdate((WindowPtr) gtheEvent.message);
  323.         break;
  324.         
  325.         case mouseDown:
  326.             switch (FindWindow(gtheEvent.where, &whichWindow)) {
  327.                 case inSysWindow:
  328.                     SystemClick(>heEvent, whichWindow);
  329.                 break;
  330.                         
  331.                 case inDrag:
  332.                     DragWindow(whichWindow, gtheEvent.where, &qd.screenBits.bounds);
  333.                 break;
  334.  
  335.                 case inGoAway:
  336.                     if (TrackGoAway(whichWindow, gtheEvent.where))
  337.                         return false;
  338.                 break;
  339.                 
  340.                 case inContent:
  341.                     if (whichWindow != FrontWindow())
  342.                          SelectWindow(whichWindow);
  343.                      else
  344.                      {
  345.                          gxPoint        mouseLoc;
  346.                          Point        currMouseLoc;
  347.                          
  348.                          currMouseLoc.h = gtheEvent.where.h;
  349.                          currMouseLoc.v = gtheEvent.where.v;
  350.                          
  351.                         GXConvertQDPoint(&currMouseLoc, gTheWindowsViewPort, &mouseLoc);
  352.  
  353.                          DoClick(mouseLoc, gWindow);
  354.                      }
  355.                 break;
  356.  
  357.             }
  358.             
  359.         case kOSEvent:
  360.             switch ((unsigned long) gtheEvent.message >> 24) {    //  high byte of message
  361.                  case kSuspendResumeMessage:            //  suspend/resume is also an activate/deactivate
  362.                     if ((gtheEvent.message & kResumeMask) == 0)
  363.                        sleep = 80;                    // we are headed to the background, so slow down...  
  364.                     else
  365.                        sleep = 0;                    // we are headed to the foreground, so speed up... 
  366.                 break;
  367.             }
  368.                 break;
  369.     }
  370.     return true;
  371. }
  372.  
  373.